home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C
/
Frameworks
/
TransSkel 3.24
/
Demos
/
C Demos
/
MultiSkel
/
MSkelHelp.c
< prev
next >
Wrap
Text File
|
1995-03-21
|
8KB
|
317 lines
/*
* TransSkel multiple-window demonstration: Help module
*
* This module handles a help window, in which text may be scrolled but
* not edited. A TextEdit record is used to hold the text, though.
*
* 21 Apr 88 Paul DuBois
* 29 Jan 89
* - Conversion for TransSkel 2.0.
* 12 Jan 91
* - Conversion for TransSkel 3.0.
*/
# include "TransSkel.h"
# include "MultiSkel.h"
static TEHandle teHelp; /* handle to help window TextEdit record */
static ControlHandle helpScroll; /* help window scroll bar */
static short helpLine; /* line currently at top of window */
static short halfPage; /* number of lines in half a window */
/*
* Scroll to the correct position. lDelta is the
* amount to CHANGE the current scroll setting by.
*/
static void
DoScroll (short lDelta)
{
short newLine;
newLine = helpLine + lDelta;
if (newLine < 0)
newLine = 0;
if (newLine > GetControlMaximum (helpScroll))
newLine = GetControlMaximum (helpScroll);
SetControlValue (helpScroll, newLine);
lDelta = (helpLine - newLine ) * (**teHelp).lineHeight;
TEScroll (0, lDelta, teHelp);
helpLine = newLine;
}
/*
* Filter proc for tracking mousedown in scroll bar. The part code
* of the part originally hit is stored as the control's reference
* value.
*
* The "void" had better be there! Otherwise the compiler will treat
* it as an integer function, not a procedure.
*/
static pascal void
TrackScroll (ControlHandle theScroll, short partCode)
{
short lDelta;
if (partCode == GetControlReference (theScroll)) /* still in same part? */
{
switch (partCode)
{
# if skelUnivHeaders > 1
case kInUpButtonControlPart: lDelta = -1; break;
case kInDownButtonControlPart: lDelta = 1; break;
case kInPageUpControlPart: lDelta = -halfPage; break;
case kInPageDownControlPart: lDelta = halfPage; break;
# else
case inUpButton: lDelta = -1; break;
case inDownButton: lDelta = 1; break;
case inPageUp: lDelta = -halfPage; break;
case inPageDown: lDelta = halfPage; break;
# endif
}
DoScroll (lDelta);
}
}
/* Compatibility machinery for non-universal header compilation */
# if !skelUnivHeaders
typedef pascal void (*ControlActionProcPtr)(ControlHandle theControl, short partCode);
typedef ControlActionProcPtr ControlActionUPP;
# endif
/*
* Set up a variable to point to the scroll tracking procedure. For 68K code this
* is just a direct pointer to TrackScroll(). For PowerPC code it is a
* routine descriptor into which the address of TrackScroll() is stuffed.
*/
# if skelPPC /* PowerPC code */
static RoutineDescriptor trackDesc =
BUILD_ROUTINE_DESCRIPTOR(uppControlActionProcInfo, TrackScroll);
static ControlActionUPP trackProc = (ControlActionUPP) &trackDesc;
# else /* 68K code */
static ControlActionUPP trackProc = TrackScroll;
# endif
/*
* Handle hits in scroll bar
*/
static pascal void
Mouse (Point pt, long t, short mods)
{
short thePart;
# if skelUnivHeaders > 1
if ((thePart = TestControl (helpScroll, pt)) == kInIndicatorControlPart)
# else
if ((thePart = TestControl (helpScroll, pt)) == inThumb)
# endif
{
(void) TrackControl (helpScroll, pt, nil);
DoScroll (GetControlValue (helpScroll) - helpLine);
}
else if (thePart != 0)
{
SetControlReference (helpScroll, (long) thePart);
(void) TrackControl (helpScroll, pt, trackProc);
}
}
/*
* Update help window. The update event might be in response to a
* window resizing. If so, resize the rects and recalc the linestarts
* of the text. To resize the rects, only the right edge of the
* destRect need be changed (the bottom is not used, and the left and
* top should not be changed). The viewRect should be sized to the
* screen. Pull text down if necessary to fill window.
*/
static pascal void
Update (Boolean resized)
{
Rect r;
short visLines;
short lHeight;
short topLines;
short nLines;
short scrollLines;
r = helpWind->portRect;
EraseRect (&r);
if (resized)
{
r.left += 4;
r.bottom -= 2;
r.top += 2;
r.right -= 19;
(**teHelp).destRect.right = r.right;
(**teHelp).viewRect = r;
TECalText (teHelp);
lHeight = (**teHelp).lineHeight;
nLines = (**teHelp).nLines;
visLines = (r.bottom - r.top) / lHeight;
halfPage = visLines / 2;
topLines = (r.top - (**teHelp).destRect.top) / lHeight;
scrollLines = visLines - (nLines - topLines);
if (scrollLines > 0 && topLines > 0)
{
if (scrollLines > topLines)
scrollLines = topLines;
TEScroll (0, scrollLines * lHeight, teHelp);
}
scrollLines = nLines - visLines;
helpLine = (r.top - (**teHelp).destRect.top) / lHeight;
/*
* Move and resize the scroll bar as well. The ValidRect call is done
* because the HideControl adds the control bounds box to the update
* region - which would generate another update event! Since everything
* gets redrawn below, the ValidRect is used to cancel the update.
*/
HideControl (helpScroll);
r = helpWind->portRect;
r.left = r.right - 15;
r.bottom -= 14;
--r.top;
++r.right;
SizeControl (helpScroll, r.right - r.left, r.bottom - r.top);
MoveControl (helpScroll, r.left, r.top);
SetControlMaximum (helpScroll, nLines - visLines < 0 ? 0 : nLines - visLines);
SetControlValue (helpScroll, helpLine);
/*if (scrollLines <= 0)
HiliteControl (helpScroll, (scrollLines > 0 ? 0 : 255));*/
ShowControl (helpScroll);
/*if (GetControlValue (helpScroll) > scrollLines)
DoScroll (GetControlValue (helpScroll) - scrollLines);*/
}
DrawGrowBox (helpWind);
DrawControls (helpWind); /* redraw scroll bar */
r = (**teHelp).viewRect;
TEUpdate (&r, teHelp); /* redraw text display */
ValidRect (&helpWind->portRect);
}
/*
* When the window comes active, disable the Edit menu and highlight
* the scroll bar if there are any lines not visible in the content
* region. When the window is deactivated, enable the Edit menu and
* un-highlight the scroll bar.
*/
static pascal void
Activate (Boolean active)
{
DrawGrowBox (helpWind);
if (active)
{
DisableItem (editMenu, 0);
HiliteControl (helpScroll,
(GetControlMaximum (helpScroll) > 0 ? normalHilite : dimHilite));
}
else
{
EnableItem (editMenu, 0);
HiliteControl (helpScroll, dimHilite);
}
DrawMenuBar ();
}
static pascal void
Clobber (void)
{
TEDispose (teHelp);
DisposeControl (helpScroll);
DisposeWindow (helpWind);
}
void
HelpWindInit (void)
{
Rect r;
Handle textHandle;
short visLines;
short scrollLines;
if (SkelQuery (skelQHasColorQD))
helpWind = GetNewCWindow (helpWindRes, nil, (WindowPtr) -1L);
else
helpWind = GetNewWindow (helpWindRes, nil, (WindowPtr) -1L);
if (helpWind == (WindowPtr) nil)
return;
(void) SkelWindow (helpWind,
Mouse, /* handle clicks in scrollbar */
nil, /* ignore keyclicks */
Update,
Activate,
nil, /* no close proc */
Clobber, /* disposal proc */
nil, /* no idle proc */
false);
TextFont (0);
TextSize (0);
r = helpWind->portRect;
r.left += 4;
r.bottom -= 2;
r.top += 2;
r.right -= 19;
teHelp = TENew (&r, &r);
textHandle = GetResource ('TEXT', helpTextRes); /* read help text */
HLock (textHandle); /* lock it and insert into TERec */
TEInsert (*textHandle, GetHandleSize (textHandle), teHelp);
HUnlock (textHandle);
ReleaseResource (textHandle); /* done with it, so goodbye */
/*
* Now figure out how many lines will fit in the window and how many
* will not. Determine the number of lines in half a window for use
* in tracking clicks in the page up and page down regions of the
* scroll bar. Then create the scroll bar . Make sure the borders
* overlap the window frame and the frame of the grow box.
*/
visLines = (r.bottom - r.top) / (**teHelp).lineHeight;
scrollLines = (**teHelp).nLines - visLines;
halfPage = visLines / 2;
helpLine = 0;
r = helpWind->portRect;
r.left = r.right - 15;
r.bottom -= 14;
--r.top;
++r.right;
/*
* Build the scroll bar. Don't need to bother testing whether to
* highlight it or not, since that will be done in response to the
* activate event.
*/
helpScroll = NewControl (helpWind, &r, "\p", true,
helpLine, 0, scrollLines, scrollBarProc, 0L);
/*
* GetNewWindow generates an update event for entire portRect.
* Cancel it, since the everything has been drawn already,
* except for the grow box (which will be drawn in response
* to the activate event).
*/
ValidRect (&helpWind->portRect);
}